El presente trabajo tiene como objetivo aplicar técnicas de
aprendizaje no supervisado, específicamente algoritmos de clustering,
para analizar y segmentar un conjunto de datos. Se ha seleccionado el
conjunto de datos iris, incluido en R base, que constituye
uno de los conjuntos de datos más conocidos en la estadística y el
aprendizaje automático.
El conjunto de datos iris contiene información sobre 150
flores del género Iris pertenecientes a tres especies diferentes: Iris
setosa, Iris versicolor e Iris virginica. Para cada espécimen, se han
registrado cuatro variables morfológicas medidas en centímetros:
Este conjunto de datos fue recopilado por el botánico británico Edgar Anderson y posteriormente utilizado por Ronald Fisher en su trabajo seminal sobre análisis discriminante. La riqueza de este conjunto radica en que las especies están distribuidas de tal manera que una de ellas (setosa) es linealmente separable de las otras dos, mientras que las especies versicolor y virginica presentan cierto solapamiento, lo que lo convierte en un excelente caso de estudio para técnicas de clustering.
El objetivo del análisis es encontrar agrupaciones naturales en los datos utilizando únicamente las características morfológicas, y posteriormente contrastar si estas agrupaciones corresponden con las especies biológicas conocidas.
Como primer paso, se procede a cargar y examinar el conjunto de datos para comprender su estructura y características básicas.
data <- iris %>%
dplyr::select(-Species) %>%
glimpse()
## Rows: 150
## Columns: 4
## $ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.…
## $ Sepal.Width <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…
## $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.…
## $ Petal.Width <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
Se realizan visualizaciones bivariantes para explorar las relaciones entre las diferentes variables medidas y detectar posibles patrones o agrupaciones naturales en los datos.
plot.sl_sw <- data %>%
ggplot() +
aes(x = Sepal.Length,
y = Sepal.Width) +
geom_point() +
theme_bw() +
labs(title = "Relación entre longitud y anchura del sépalo",
x = "Longitud del sépalo (cm)",
y = "Anchura del sépalo (cm)")
plot.pl_pw <- data %>%
ggplot() +
aes(x = Petal.Length,
y = Petal.Width) +
geom_point() +
theme_bw() +
labs(title = "Relación entre longitud y anchura del pétalo",
x = "Longitud del pétalo (cm)",
y = "Anchura del pétalo (cm)")
plot.sl_pl <- data %>%
ggplot() +
aes(x = Sepal.Length,
y = Petal.Length) +
geom_point() +
theme_bw() +
labs(title = "Relación entre longitud del sépalo y del pétalo",
x = "Longitud del sépalo (cm)",
y = "Longitud del pétalo (cm)")
library(ggpubr)
ggarrange(plot.sl_sw,
plot.pl_pw,
plot.sl_pl,
ncol=1,nrow=3)
En la visualización de las relaciones bivariantes, se pueden observar patrones interesantes:
Para una mejor comprensión de la estructura multidimensional de los datos, se visualizan las relaciones entre tres variables simultáneamente:
data %>%
ggplot() +
aes(x = Sepal.Length,
y = Petal.Length,
color = Petal.Width) +
labs(x="Longitud del sépalo (cm)",
y="Longitud del pétalo (cm)",
title="Relación entre medidas florales") +
scale_color_continuous(name="Anchura del pétalo (cm)") +
geom_point(size = 2) +
theme_bw()
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
data %>%
plot_ly(x = ~ Sepal.Length,
y = ~ Petal.Length,
z = ~ Petal.Width,
color = ~ Sepal.Width,
type = "scatter3d",
mode = "markers"
) %>%
layout(scene = list(xaxis = list(title = "Longitud del sépalo (cm)"),
yaxis = list(title = "Longitud del pétalo (cm)"),
zaxis = list(title = "Anchura del pétalo (cm)")),
title = "Visualización tridimensional de las características florales")
Es importante verificar la presencia de valores atípicos o ausentes en el conjunto de datos, ya que podrían afectar al rendimiento de los algoritmos de clustering.
# Verificación de valores ausentes
sum(is.na(data))
## [1] 0
# Resumen estadístico para detección de posibles valores atípicos
summary(data)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
# Visualización de diagramas de caja para detectar valores atípicos
par(mfrow=c(2,2))
for(i in 1:4) {
boxplot(data[,i], main=names(data)[i], col="lightblue")
}
No se detectan valores ausentes en el conjunto de datos. Los diagramas de caja muestran algunos valores potencialmente atípicos, pero dado el contexto biológico y el tamaño limitado de la muestra, se decide mantenerlos para el análisis de clustering, ya que podrían representar variabilidad natural dentro de las especies.
A diferencia de otros conjuntos de datos que pueden requerir
transformaciones logarítmicas para manejar distribuciones asimétricas,
las variables en el conjunto iris se encuentran en escalas
relativamente similares (todas medidas en centímetros). Sin embargo,
existen diferencias en los rangos de las variables que podrían influir
en los algoritmos de clustering basados en distancia.
Por lo tanto, se procede a estandarizar las variables para que todas contribuyan equitativamente al análisis:
data_scaled <- data %>%
mutate(
across(everything(),
~ as.numeric(scale(.))
)
) %>%
glimpse()
## Rows: 150
## Columns: 4
## $ Sepal.Length <dbl> -0.89767388, -1.13920048, -1.38072709, -1.50149039, -1.01…
## $ Sepal.Width <dbl> 1.01560199, -0.13153881, 0.32731751, 0.09788935, 1.245030…
## $ Petal.Length <dbl> -1.335752, -1.335752, -1.392399, -1.279104, -1.335752, -1…
## $ Petal.Width <dbl> -1.3110521, -1.3110521, -1.3110521, -1.3110521, -1.311052…
La estandarización convierte cada variable a una escala con media 0 y desviación estándar 1, eliminando así el efecto de las diferentes unidades de medida y magnitudes en el análisis de clustering.
El agrupamiento jerárquico es una técnica que construye una jerarquía de clusters mediante un proceso iterativo. En este trabajo, se aplicará esta técnica con diferentes combinaciones de medidas de disparidad entre observaciones y entre clusters.
# Elegimos la distancia euclidiana
dist_eucli <- dist(data_scaled, method="euclidean")
Justificación de la elección de distancia Euclidiana:
La distancia euclidiana ha sido seleccionada como medida de disparidad entre observaciones por las siguientes razones:
Interpretabilidad geométrica: Las medidas de pétalos y sépalos representan distancias físicas en el espacio, y la distancia euclidiana corresponde directamente al concepto intuitivo de distancia en un espacio geométrico.
Correlación entre variables: Las características morfológicas de las flores (longitud y anchura) están correlacionadas naturalmente, y la distancia euclidiana captura adecuadamente estas relaciones.
Variables en la misma escala: Después de la estandarización, todas las variables están en la misma escala, haciendo que la distancia euclidiana sea equitativa en su ponderación de cada característica.
Sensibilidad a diferencias grandes: La distancia euclidiana, al elevar al cuadrado las diferencias, es más sensible a diferencias grandes entre especies, lo que es útil para identificar grupos bien diferenciados como en el caso de las especies de Iris.
Para evaluar el impacto del método de enlace en los resultados del clustering jerárquico, se compararán dos enfoques: el método de Ward y el método de enlace completo.
library(ggdendro)
# Aplicamos el método de Ward
model_dendo.ward <- dist_eucli %>%
hclust(method = "ward.D")
model_dendo.ward %>%
ggdendrogram(
rotate = FALSE,
labels = FALSE,
theme_dendro = TRUE
) +
labs(title = "Dendograma con método de Ward")
Justificación de la elección del método de Ward:
El método de Ward es considerado apropiado para el conjunto de datos Iris por los siguientes motivos:
Minimización de la varianza: Ward busca minimizar la suma de cuadrados dentro de cada cluster, lo que resulta en grupos homogéneos y es ideal para identificar grupos compactos como las especies de Iris.
Robustez frente a valores atípicos: En comparación con otros métodos, Ward es menos susceptible al efecto de encadenamiento y produce clusters más equilibrados en tamaño.
Coherencia con k-means: El método de Ward utiliza criterios similares a k-means (minimización de varianza), lo que facilita la comparación entre ambos métodos de clustering.
Evidencia empírica: En numerosos estudios comparativos de técnicas de clustering, el método de Ward ha demostrado un rendimiento superior para conjuntos de datos con clusters bien definidos y de tamaño similar, como es el caso del conjunto de datos Iris.
# Aplicamos el método de enlace completo
model_dendo.complete <- dist_eucli %>%
hclust(method = "complete")
model_dendo.complete %>%
ggdendrogram(
rotate = FALSE,
labels = FALSE,
theme_dendro = TRUE
) +
labs(title = "Dendograma con método de enlace completo")
Comparación entre métodos de enlace:
El método de enlace completo define la distancia entre clusters como la máxima distancia entre cualquier par de puntos pertenecientes a clusters diferentes. En comparación con el método de Ward:
Forma de los clusters: El enlace completo tiende a formar clusters más compactos y de tamaño similar, pero puede ser sensible a valores atípicos.
Estructura jerárquica: El dendrograma resultante muestra una estructura diferente, con ramificaciones más pronunciadas que pueden dificultar la identificación del número óptimo de clusters.
Interpretabilidad: En el contexto de las características morfológicas de las flores, el enlace completo podría no capturar tan bien la variabilidad natural dentro de cada especie como lo hace el método de Ward.
library(dendextend)
##
## ---------------------
## Welcome to dendextend version 1.19.0
## Type citation('dendextend') for how to cite the package.
##
## Type browseVignettes(package = 'dendextend') for the package vignette.
## The github page is: https://github.com/talgalili/dendextend/
##
## Suggestions and bug-reports can be submitted at: https://github.com/talgalili/dendextend/issues
## You may ask questions at stackoverflow, use the r and dendextend tags:
## https://stackoverflow.com/questions/tagged/dendextend
##
## To suppress this message use: suppressPackageStartupMessages(library(dendextend))
## ---------------------
##
## Attaching package: 'dendextend'
## The following object is masked from 'package:ggdendro':
##
## theme_dendro
## The following object is masked from 'package:ggpubr':
##
## rotate
## The following object is masked from 'package:stats':
##
## cutree
# Visualización mejorada del dendrograma con método de Ward
dend_ward <- model_dendo.ward %>%
as.dendrogram() %>%
color_branches(k = 3) %>%
color_labels(k = 3) %>% #colorea según el clúster
set("labels_cex", 0.4)
# Visualización mejorada del dendrograma con método de enlace completo
dend_complete <- model_dendo.complete %>%
as.dendrogram() %>%
color_branches(k = 3) %>%
color_labels(k = 3) %>%
set("labels_cex", 0.4)
# Comparación visual
par(mfrow=c(1,2))
plot(dend_ward, main = "Método de Ward", ylab = "Altura (disimilitud)")
abline(h = 15, lty=2)
plot(dend_complete, main = "Método de enlace completo", ylab = "Altura (disimilitud)")
abline(h = 15, lty=2)
La comparación visual de los dendrogramas revela diferencias significativas en la estructura jerárquica producida por cada método de enlace. El método de Ward tiende a producir clusters más equilibrados y una jerarquía más clara, mientras que el enlace completo muestra una estructura más irregular.
Para determinar el número óptimo de clusters en el agrupamiento jerárquico, se utiliza el método de la silueta, que evalúa la calidad de los clusters en función de la cohesión interna y la separación entre clusters.
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
data_scaled %>%
fviz_nbclust(FUNcluster = hcut,
method = "silhouette",
k.max = 10) +
labs(title = "Número óptimo de clusters según el método de la silueta")
El método de la silueta sugiere que el número óptimo de clusters es 2. Sin embargo, teniendo en cuenta el conocimiento previo de que existen tres especies de Iris en el conjunto de datos, y considerando la estructura observada en el análisis exploratorio, se decide proceder con 3 clusters para el análisis.
# Visualización del dendrograma con 3 clusters
model_dendo.ward %>%
fviz_dend(k = 3,
rect = TRUE,
horiz = FALSE,
rect_border = "gray",
rect_fill = FALSE,
cex = 0.4,
lwd = 0.2,
k_colors = c("red","blue","green"),
ggtheme = theme_bw()
)
## Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as
## of ggplot2 3.3.4.
## ℹ The deprecated feature was likely used in the factoextra package.
## Please report the issue at <https://github.com/kassambara/factoextra/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Para una comprensión más completa de la estructura jerárquica, se presentan representaciones alternativas del dendrograma:
# Representación filogenética del dendrograma
model_dendo.ward %>%
fviz_dend(k = 3,
rect = TRUE,
horiz = FALSE,
rect_border = "gray",
rect_fill = FALSE,
cex = 0.4,
lwd = 0.2,
k_colors = c("red","blue","green"),
ggtheme = theme_bw(),
type = "phylogenic",
main = "Representación filogenética (método de Ward)"
)
# Representación circular del dendrograma
model_dendo.ward %>%
fviz_dend(k = 3,
rect = TRUE,
horiz = FALSE,
rect_border = "gray",
rect_fill = FALSE,
cex = 0.4,
lwd = 0.2,
k_colors = c("red","blue","green"),
ggtheme = theme_bw(),
type = "circular",
main = "Representación circular (método de Ward)"
)
Para evaluar la calidad del clustering jerárquico, se utiliza el análisis de silueta, que proporciona una medida de cuán bien está asignada cada observación a su cluster.
# Análisis de silueta para el método de Ward
library(cluster)
fviz_silhouette(
silhouette(cutree(model_dendo.ward, k = 3), dist_eucli),
palette = c("red", "blue", "green"),
ggtheme = theme_bw()
) +
labs(title = "Análisis de silueta para clustering jerárquico (método de Ward)")
## cluster size ave.sil.width
## 1 1 49 0.67
## 2 2 74 0.32
## 3 3 27 0.45
# Análisis de silueta para el método de enlace completo
fviz_silhouette(
silhouette(cutree(model_dendo.complete, k = 3), dist_eucli),
palette = c("red", "blue", "green"),
ggtheme = theme_bw()
) +
labs(title = "Análisis de silueta para clustering jerárquico (enlace completo)")
## cluster size ave.sil.width
## 1 1 49 0.64
## 2 2 24 0.48
## 3 3 77 0.32
Interpretación del análisis de silueta:
El análisis de silueta revela la calidad de la asignación de las observaciones a los clusters. Los valores de silueta próximos a 1 indican una buena asignación, mientras que valores cercanos a 0 o negativos sugieren posibles asignaciones incorrectas.
Se observa que: - El método de Ward produce clusters con valores de silueta generalmente más altos, lo que indica una mejor separación entre clusters. - El método de enlace completo muestra valores de silueta más variables, con algunas observaciones potencialmente mal asignadas.
Basándose en estos resultados, se decide proceder con el método de Ward para la construcción final de los clusters.
data_scaled <- data_scaled %>%
mutate(
cluster_jerar = factor(model_dendo.ward %>%
cutree(k = 3))
) %>%
glimpse()
## Rows: 150
## Columns: 5
## $ Sepal.Length <dbl> -0.89767388, -1.13920048, -1.38072709, -1.50149039, -1.0…
## $ Sepal.Width <dbl> 1.01560199, -0.13153881, 0.32731751, 0.09788935, 1.24503…
## $ Petal.Length <dbl> -1.335752, -1.335752, -1.392399, -1.279104, -1.335752, -…
## $ Petal.Width <dbl> -1.3110521, -1.3110521, -1.3110521, -1.3110521, -1.31105…
## $ cluster_jerar <fct> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
library(plotly)
data_scaled %>%
plot_ly(x = ~ Sepal.Length,
y = ~ Petal.Length,
z = ~ Petal.Width,
color = ~ cluster_jerar,
type = "scatter3d",
mode = "markers",
colors = c("red","blue","green")
) %>%
layout(scene = list(xaxis = list(title = "Longitud del sépalo (estand.)"),
yaxis = list(title = "Longitud del pétalo (estand.)"),
zaxis = list(title = "Anchura del pétalo (estand.)")),
title = "Visualización 3D de clusters jerárquicos (método de Ward)")
El algoritmo k-medias es una técnica de partición que divide el conjunto de datos en k grupos, donde cada observación pertenece al cluster con el centroide más cercano.
Para determinar el número óptimo de clusters en k-medias, se utiliza el método del codo (elbow method), que examina la variación de la suma de cuadrados dentro del cluster (WSS) en función del número de clusters.
library(factoextra)
data_scaled %>%
select(-cluster_jerar) %>% #debemos eliminar esta variable
fviz_nbclust(FUNcluster = kmeans,
method = "wss") +
labs(title = "Método del codo para determinar el número óptimo de clusters",
x = "Número de clusters",
y = "Suma de cuadrados dentro del cluster (WSS)")
Justificación de la elección del número de clusters:
El gráfico del método del codo muestra la disminución de la suma de cuadrados dentro del cluster (WSS) a medida que aumenta el número de clusters. Se busca el punto donde esta disminución se estabiliza, formando un “codo” en el gráfico.
En este caso, se puede observar un codo en k=3, lo que sugiere que este es el número óptimo de clusters. Esta elección coincide con el conocimiento previo de que el conjunto de datos contiene tres especies de Iris.
model_kmeans <- data_scaled %>%
select(-cluster_jerar) %>%
kmeans(centers = 3,
nstart = 10)
model_kmeans
## K-means clustering with 3 clusters of sizes 53, 47, 50
##
## Cluster means:
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 -0.05005221 -0.88042696 0.3465767 0.2805873
## 2 1.13217737 0.08812645 0.9928284 1.0141287
## 3 -1.01119138 0.85041372 -1.3006301 -1.2507035
##
## Clustering vector:
## [1] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
## [38] 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 2 1 1 1
## [75] 1 2 2 2 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 2 2 2 2 1 2 2 2 2
## [112] 2 2 1 1 2 2 2 2 1 2 1 2 1 2 2 1 2 2 2 2 2 2 1 1 2 2 2 1 2 2 2 1 2 2 2 1 2
## [149] 2 1
##
## Within cluster sum of squares by cluster:
## [1] 44.08754 47.45019 47.35062
## (between_SS / total_SS = 76.7 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
# Distribución de observaciones en los clusters
table(model_kmeans$cluster)
##
## 1 2 3
## 53 47 50
data_scaled <- data_scaled %>%
mutate(
cluster_kmeans = factor(model_kmeans$cluster)
) %>%
glimpse()
## Rows: 150
## Columns: 6
## $ Sepal.Length <dbl> -0.89767388, -1.13920048, -1.38072709, -1.50149039, -1.…
## $ Sepal.Width <dbl> 1.01560199, -0.13153881, 0.32731751, 0.09788935, 1.2450…
## $ Petal.Length <dbl> -1.335752, -1.335752, -1.392399, -1.279104, -1.335752, …
## $ Petal.Width <dbl> -1.3110521, -1.3110521, -1.3110521, -1.3110521, -1.3110…
## $ cluster_jerar <fct> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ cluster_kmeans <fct> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3…
library(plotly)
data_scaled %>%
plot_ly(x = ~ Sepal.Length,
y = ~ Petal.Length,
z = ~ Petal.Width,
color = ~ cluster_kmeans,
type = "scatter3d",
mode = "markers",
colors = c("red","blue","green")
) %>%
layout(scene = list(xaxis = list(title = "Longitud del sépalo (estand.)"),
yaxis = list(title = "Longitud del pétalo (estand.)"),
zaxis = list(title = "Anchura del pétalo (estand.)")),
title = "Visualización 3D de clusters K-medias")
library(factoextra)
model_kmeans %>%
fviz_cluster(
data = data_scaled %>% select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width),
geom = "point",
palette = c("red","blue","green"),
ellipse = TRUE,
ellipse.type = "euclid",
star.plot = TRUE,
repel = TRUE,
ggtheme = theme_bw()
) +
labs(title = "Visualización de clusters K-medias con elipses de confianza")
Para evaluar la efectividad de los algoritmos de clustering, se comparan los clusters obtenidos con las especies biológicas conocidas:
# Añadimos las especies reales para comparar
data_comparison <- data_scaled %>%
mutate(Species = iris$Species)
# Tabla de contingencia entre cluster k-means y especies
tabla_kmeans <- table(data_comparison$cluster_kmeans, data_comparison$Species)
print("Comparación de K-medias con especies reales:")
## [1] "Comparación de K-medias con especies reales:"
print(tabla_kmeans)
##
## setosa versicolor virginica
## 1 0 39 14
## 2 0 11 36
## 3 50 0 0
# Tabla de contingencia entre cluster jerárquico y especies
tabla_jerar <- table(data_comparison$cluster_jerar, data_comparison$Species)
print("Comparación de clustering jerárquico con especies reales:")
## [1] "Comparación de clustering jerárquico con especies reales:"
print(tabla_jerar)
##
## setosa versicolor virginica
## 1 49 0 0
## 2 1 50 23
## 3 0 0 27
# Cálculo de precisión para K-medias
precision_kmeans <- sum(diag(tabla_kmeans)) / sum(tabla_kmeans)
cat("Precisión de K-medias:", round(precision_kmeans*100, 2), "%\n")
## Precisión de K-medias: 7.33 %
# Cálculo de precisión para clustering jerárquico
precision_jerar <- sum(diag(tabla_jerar)) / sum(tabla_jerar)
cat("Precisión de clustering jerárquico:", round(precision_jerar*100, 2), "%\n")
## Precisión de clustering jerárquico: 84 %
# Visualización con las especies reales
ggplot(data_comparison, aes(x = Petal.Length, y = Petal.Width, color = Species, shape = cluster_kmeans)) +
geom_point(size = 3) +
labs(title = "Comparación de clusters K-medias con especies reales",
x = "Longitud del pétalo (estand.)",
y = "Anchura del pétalo (estand.)") +
theme_bw()
ggplot(data_comparison, aes(x = Petal.Length, y = Petal.Width, color = Species, shape = cluster_jerar)) +
geom_point(size = 3) +
labs(title = "Comparación de clusters jerárquicos con especies reales",
x = "Longitud del pétalo (estand.)",
y = "Anchura del pétalo (estand.)") +
theme_bw()
# Matriz de gráficos de dispersión coloreados por especie y clusters
library(GGally)
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
# Seleccionamos variables relevantes para la visualización
data_viz <- data_comparison %>%
select(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species, cluster_kmeans, cluster_jerar)
# Matriz para clusters K-medias
ggpairs(data_viz,
columns = 1:4,
aes(color = cluster_kmeans),
upper = list(continuous = "points"),
diag = list(continuous = "densityDiag"),
lower = list(continuous = "points")) +
theme_bw() +
labs(title = "Matriz de dispersión por clusters K-medias")
# Matriz para clusters jerárquicos
ggpairs(data_viz,
columns = 1:4,
aes(color = cluster_jerar),
upper = list(continuous = "points"),
diag = list(continuous = "densityDiag"),
lower = list(continuous = "points")) +
theme_bw() +
labs(title = "Matriz de dispersión por clusters jerárquicos")
# Matriz por especies reales
ggpairs(data_viz,
columns = 1:4,
aes(color = Species),
upper = list(continuous = "points"),
diag = list(continuous = "densityDiag"),
lower = list(continuous = "points")) +
theme_bw() +
labs(title = "Matriz de dispersión por especies reales")
Tras aplicar dos técnicas diferentes de clustering al conjunto de datos Iris, se pueden extraer las siguientes conclusiones:
Eficacia de las técnicas de clustering: Tanto el agrupamiento jerárquico con el método de Ward como el algoritmo K-medias han demostrado ser eficaces para identificar las agrupaciones naturales en el conjunto de datos Iris, logrando una alta correspondencia con las especies biológicas conocidas.
Comparación de métodos:
Número óptimo de clusters: Aunque el análisis de silueta sugirió inicialmente 2 clusters como número óptimo, la incorporación del conocimiento previo sobre la existencia de 3 especies y el análisis del método del codo confirmaron que 3 es el número más adecuado de clusters para este conjunto de datos.
Características discriminatorias: Las variables relacionadas con el pétalo (longitud y anchura) resultaron ser más discriminatorias que las variables del sépalo para la identificación de las especies de Iris, como se evidencia en las visualizaciones multivariantes.
Implicaciones biológicas: Los resultados del clustering sugieren que las características morfológicas medidas son suficientes para diferenciar las tres especies de Iris, con una separación particularmente clara de Iris setosa respecto a las otras dos especies, mientras que Iris versicolor e Iris virginica presentan cierto solapamiento.
Limitaciones y trabajo futuro:
En conclusión, este trabajo demuestra la utilidad de las técnicas de clustering para identificar patrones naturales en datos multivariantes y su aplicabilidad en contextos biológicos como la clasificación taxonómica. Los resultados obtenidos validan la separación morfológica de las tres especies de Iris estudiadas, mostrando la eficacia tanto del agrupamiento jerárquico como del algoritmo K-medias cuando se aplican con las medidas de disparidad y parámetros adecuados.